﻿using System;
using System.Linq;
using System.Net;
using System.IO;
using System.Collections.Generic;
using System.Threading;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Administration;

namespace CodeCounsel.SharePoint2010.DigiD
{
    abstract class WebRequest<TResponse>
        where TResponse : WebResponse
    {
        protected DigiDSettings Settings { get; private set; }

        protected WebRequest(DigiDSettings settings)
        {
            Settings = settings;
        }

        public virtual TResponse GetResponse()
        {
            string responseText = null;
            try
            {
                using (SPMonitoredScope scope = new SPMonitoredScope("DigiD Request"))
                {
                    Uri uri = BuildRequestUrl();
                    SPDiagnosticsService.Local.WriteTrace(
                        0, new SPDiagnosticsCategory("DigiD", TraceSeverity.Verbose, EventSeverity.Verbose),
                        TraceSeverity.Verbose, "Calling DigiD using URL {0}", uri);
                    HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(uri);
                    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                    using (StreamReader reader = new StreamReader(response.GetResponseStream()))
                    {
                        responseText = reader.ReadToEnd();
                    }
                }
            }
            catch (WebException e)
            {
                throw new DigiDException("Could not connect to DigiD.", e);
            }
            Dictionary<string, string> responseParameters = Extensions.GetQuery(responseText);
            TResponse digiDResponse = CreateResponse(responseParameters);
            ValidateResponse(digiDResponse);
            return digiDResponse;
        }

        protected virtual void ValidateResponse(TResponse digiDResponse)
        {
            if (digiDResponse.ResultCode != ResultCode.Ok)
            {
                throw new DigiDException("Unexpected result code " + digiDResponse.ResultCode);
            }
        }

        protected virtual void GetParameters(Dictionary<string, string> requestParameters) { }

        protected abstract TResponse CreateResponse(Dictionary<string, string> responseParameters);

        Uri BuildRequestUrl()
        {
            UriBuilder builder = new UriBuilder(Settings.ServerUrl);
            Dictionary<string, string> requestParameters = builder.GetQuery();
            GetParameters(requestParameters);
            builder.SetQuery(requestParameters);
            return builder.Uri;
        }
    }
}
